package com.zhuyuan.auth.config;

import com.zhuyuan.auth.sms.SmsCodeAuthenticationProvider;
import com.zhuyuan.auth.social.SocialAuthenticationProvider;
import com.zhuyuan.security.handler.FailureHandler;
import com.zhuyuan.security.handler.LogoutHandler;
import com.zhuyuan.security.handler.SuccessHandler;
import com.zhuyuan.security.service.BaseUserDetailsService;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;

/**
 * @Author: 张琳凯
 * @Description: Security配置类
 * @DateTime: 2025/1/6 20:42
 **/
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    private final SuccessHandler successHandler;
    private final FailureHandler failureHandler;
    private final LogoutHandler logoutHandler;
    private final BaseUserDetailsService userDetailService;

    /**
     * 配置认证管理器，springsecurity通过认证管理器来实现认证
     */
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManager();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * 不拦截静态资源
     *
     * @param web
     */
    @Override
    public void configure(WebSecurity web) throws Exception{

        web.ignoring().antMatchers(
                "/css/**",
                "/swagger-ui/index.html",
                "/swagger-ui.html",
                "/swagger-ui/**",
                "/v3/api-docs/**",
                "/v3/api-docs"
        );
    }

    /**
     * 用户自定义和管理身份验证
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.
                userDetailsService(userDetailService)
                .passwordEncoder(passwordEncoder());
        auth.authenticationProvider(new SmsCodeAuthenticationProvider(userDetailService));
        auth.authenticationProvider(new SocialAuthenticationProvider(userDetailService));
    }


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()// 禁用csrf
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)//禁用会话
                .and()
//                .requestMatchers().antMatchers("/auth/**").and()
                .authorizeRequests()// 配置接口的拦截
                .antMatchers("/auth/login","/auth/code","/auth/test").permitAll()// 配置放行接口
//                .antMatchers("/user/info/**").access("@internalAccessValidator.isInternalRequest(request)")
                .anyRequest().authenticated()//  其余接口都需要认证
                .and().formLogin().disable()
//                .successHandler(successHandler).permitAll()
//                .failureHandler(failureHandler).permitAll()
//                .and()
//                .logout().logoutSuccessHandler(logoutHandler)
        ;
    }

}

